﻿using System;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Security.Cryptography;

namespace Attacker
{
    class Mark
    {
        private int[] tran = { 6, 7, 8, 9, 10, 11 };
        public delegate void ReturnInt(int v);
        public ReturnInt ReturnProgress;
        public delegate void ReturnString(string v);
        public ReturnString ReturnTip;
        public void Mark_Click(Database_mag data_mag, string private_key, int row_mod, int col_mod, int bit_mod)
        {
            ReturnProgress?.Invoke(10);
            ReturnTip?.Invoke("正在读取数据...");
            data_mag.Backups();//   ???
            DateTime t1 = DateTime.Now;
            Console.WriteLine("start at: " + t1.ToString() + "\r\nRead database");
            TimeSpan ts1 = new TimeSpan(t1.Ticks);
            DataTable dt = data_mag.Read_table();
            int cnt = 0;
            int ccnt = 0;
            int sum = dt.Rows.Count;
            ReturnTip?.Invoke("正在添加水印...");
            Console.WriteLine("Now change table");
            foreach (DataRow row in dt.Rows)
            {
                ccnt++;
                ReturnProgress?.Invoke(10 + ccnt / sum * 40);
                int hash = GetHash(private_key + row[0].ToString());
                if (hash % row_mod == 0)
                {
                    int col = (hash % col_mod + col_mod) % col_mod;
                    col = tran[col];
                    int bit = (hash % bit_mod + bit_mod - 1) % bit_mod + 1;
                    string pre_val = row[col].ToString();
                    int len = pre_val.Length;
                    string upd_val = pre_val.Substring(0, len - bit) + ((bit-2)%10+1).ToString() + pre_val.Substring(len - bit + 1);
                    //MessageBox.Show(pre_val + "\n" + bit.ToString() + "\n" + upd_val);
                    row[col] = upd_val;
                    cnt++;
                }
            }
            Console.WriteLine("Udpate database");
            ReturnTip?.Invoke("写回数据库...");
            ReturnProgress?.Invoke(80);
            data_mag.Update_table();
            ReturnProgress?.Invoke(100);
            DateTime t2 = DateTime.Now;
            Console.WriteLine("end at: " + t2.ToString());
            TimeSpan ts2 = new TimeSpan(t2.Ticks);
            TimeSpan ts3 = ts2.Subtract(ts1);
            MessageBox.Show(string.Format("共添加{0}条水印，用时{1}秒", cnt, (ts3.TotalMilliseconds / 1000).ToString()));
            return;
        }

        private int GetHash(string str)
        {
            byte[] sourcebytes = Encoding.Default.GetBytes(str);
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] hashedbytes = md5.ComputeHash(sourcebytes);
            return BitConverter.ToInt32(hashedbytes, 0);
        }
    }
}
